/**i
 *  \file app.c
 *
 *  \brief application layer
 *
 *  \author Michael J. Hohmann  <michael.hohmann@linde-mh.de>
 *
 *
 */

/*===============================================[ private includes  ]================================================*/
#include "app.h"
#include "../assertor/assertor.h"
#include "../sched/sched.h"
#include "../pal/pal_mem.h"
#include "../mcu/mcu.h"
#include "../contactor/contactor.h"
#include "../input/input.h"
#include "../output/output.h"
#include "../control/control.h"
#include "../kwpserver/kwpserver.h"
#include "../kwpservices/kwpservices.h"
#include "../systime/systime.h"
#include "../can/can.h"
#include "../pal/pal.h"
#include "../canid/canid.h"
#include "../cancom/cancom.h"
#include "../dtc/dtc.h"
#include "../bdi/bdi.h"
#include "../cfg/service_cfg.h"
#include "../u2c/u2c_dataexchange.h"
#include "../lithium_ion/li_ion.h"                  /* app_li_ion_initialize(), ..        */
#include "../lithium_ion/li_ion_pred_bat.h"         /* li_ion_pred_ibat_initialize(), ..  */
/*===============================================[ private defines   ]================================================*/

/*===============================================[ private datatypes ]================================================*/
/**
 * Private variables
 * \struct app_private private struct only can be called by app.c
 */
struct app_private
{
    struct tasklet task_1ms;
    struct tasklet task_10ms;
    struct tasklet task_100ms;
    struct tasklet task_idle;
    struct kwpserver_obj my_kwp;
};

/*===============================================[ private variables ]================================================*/
static struct app_private app;
static U32 timecounter_100ms = 0;
struct input_data_obj input_data;
struct output_data_obj output_data;
struct u2c_data_output_obj u2c_data_output;
struct u2c_data_input_obj  u2c_data_input;
/*===============================================[ private functions ]================================================*/
static void app_1ms_service (struct tasklet *task);
static void app_10ms_service (struct tasklet *task);
static void app_100ms_service (struct tasklet *task);
static void app_idle_service (struct tasklet *task);

static void app_kwp_tx( U8 *data );
static void app_receive_diag_msg(struct canmsg* msg, void * data );
/*===============================================[ inline functions  ]================================================*/

/*===============================================[ public functions  ]================================================*/
RC app_initialize( void )
{
   pal_memzero( &app, sizeof app);
   pal_memzero( &input_data, sizeof input_data);
   pal_memzero( &output_data, sizeof output_data);
   pal_memzero( &u2c_data_output, sizeof u2c_data_output);
   pal_memzero( &u2c_data_input, sizeof u2c_data_input);

   app_li_ion_initialize();
   li_ion_pred_ibat_initialize();

   tasklet_assign( sched_get_slice_1ms(),  &app.task_1ms,   app_1ms_service, NIL );
   tasklet_assign( sched_get_slice_10ms(), &app.task_10ms,  app_10ms_service, NIL );
   tasklet_assign( sched_get_slice_100ms(),&app.task_100ms, app_100ms_service,  NIL );
   tasklet_assign( sched_get_slice_idle(), &app.task_idle,  app_idle_service, NIL );

   output_initialize();
   input_initialize();
   control_initialize();

   kwpservices_initialize();
   kwpserver_construct( &app.my_kwp, kwpservices_table, app_kwp_tx, 0x10, 0x10, 500, 250 );

   can_install_rx_callback( can_channel_ext, canid_ext_tester_kwp_common_req, app_receive_diag_msg, NIL );
   can_install_rx_callback( can_channel_ext, canid_ext_tester_kwp_vc_req,     app_receive_diag_msg, NIL );

    
   return RC_SUCCESS;
}

/*===============================================[ private functions ]================================================*/

static void app_1ms_service (struct tasklet *task)
{
   systime_tick();
   kwpserver_cyclic_service( &app.my_kwp );
}

static void app_10ms_service (struct tasklet *task)
{
   UNREFERENCED( task );
   
   static U16 delay_count=0;

   // This is only a temporary fix to made the inputs stable
   if(delay_count)
   {
       delay_count--;
   }
   else
   {
        input_read(&input_data);

		u2c_dataexchange_10ms();

        control_everything( &input_data, &output_data );

        output_set(&output_data);
   }
}

static void app_100ms_service(struct tasklet *task)
{
    UNREFERENCED( task );
    
    timecounter_100ms++;
    #if 0
    if((timecounter_100ms % 2) == 0)   //every 200ms run once
    {
        if(BAT_TYPE_LEADACID == service->batterytype)
        {
            HrsRem(BDI_BattCharge); 
        }
        
    }
    #endif

    if((timecounter_100ms % 10) == 0)  //every 1000ms run once
    {
        if(BAT_TYPE_LEADACID == service->batterytype)
        {
            bdi_task(); 
        }
        
    }
    /* other service ... */
    /* ... */
    

    /* kepp this at bottom */
    if((timecounter_100ms % 10) == 0)  //every 1000ms run once
    {
        timecounter_100ms = 0;
    }
}
static void app_idle_service (struct tasklet *task)
{
   UNREFERENCED( task );

   control_idle_service();
   kwpserver_idle_service( &app.my_kwp );
   if(RequestCount > 0)
   {
        historyDtcTrigger();    
   }
}


/** Send KWP-Response
*
*   This callback function will be called from the KWP-Instance.
*
*   \param cantx_obj Object data pointer. This value was set by the function kwpclient_construct()
*   \param data      Data to transmit
*   \param len       Lenght of data to transmit
*
*/
static void app_kwp_tx( U8 *data )
{
    can_tx( can_channel_ext, canid_ext_vc_kwp_resp, data, 8 );
}

/** Process KWP requests
*
*   can id: 0x780, 0x780+Node ID
*
*   \param msg  Pointer to the received CAN-Message
*   \param data Object pointer. The value was set at function can_install_rx_callback()
*
*/
static void app_receive_diag_msg(struct canmsg* p_msg, void * data )
{
    kwpserver_process_msg( &app.my_kwp , canmsg_data_ptr(p_msg) ) ;
}
/***********************************************************************************************************************
 *                             Copyright 2018 Linde Material Handling. All rights reserved.                             *
 ***********************************************************************************************************************/
